#ifndef __SMART_STREAM_H__
  #define __SMART_STREAM_H__

#include <string>

#include "converter.h"

using namespace std;

//! Flexible stream class

/*!
A simple implementation for a stream, which is easier than istringstream and ostringstream to use

Implementation date: 2009
*/

class smart_stream {
private:
  string buffer;

public:
  //! sets the internal buffer to the given string
  void set_buffer(const string &value) {
    buffer = value;
  }

  //! returns the internal buffer
  const string &to_string() const {
    return buffer;
  }

  //! clears the internal buffer
  void clear() {
    buffer.clear();
  }

  //! appends 0 or 1 to the buffer
  smart_stream &operator<<(bool value) {
    buffer.append(1, '0' + value);
    return *this;
  }

  //! appends
  smart_stream &operator<<(char value) {
    buffer.append(1, value);
    return *this;
  }

  //! appends
  smart_stream &operator<<(short value) {
    string str_tmp;
    buffer.append(converter::to_string(value, str_tmp));
    return *this;
  }

  //! appends
  smart_stream &operator<<(unsigned short value) {
    string str_tmp;
    buffer.append(converter::to_string(value, str_tmp));
    return *this;
  }

  //! appends
  smart_stream &operator<<(int value) {
    string str_tmp;
    buffer.append(converter::to_string(value, str_tmp));
    return *this;
  }

  //! appends
  smart_stream &operator<<(unsigned int value) {
    string str_tmp;
    buffer.append(converter::to_string(value, str_tmp));
    return *this;
  }

  //! appends
  smart_stream &operator<<(long long value) {
    string str_tmp;
    buffer.append(converter::to_string(value, str_tmp));
    return *this;
  }

  //! appends
  smart_stream &operator<<(unsigned long long value) {
    string str_tmp;
    buffer.append(converter::to_string(value, str_tmp));
    return *this;
  }

  //! appends
  smart_stream &operator<<(double value) {
    string str_tmp;
    buffer.append(converter::to_string(value, str_tmp));
    return *this;
  }

  //! appends
  smart_stream &operator<<(const string &value) {
    buffer.append(value);
    return *this;
  }

  //! returns
  smart_stream &operator>>(bool &value) {
    value = (buffer == "1");
    return *this;
  }

  //! returns
  smart_stream &operator>>(char &value) {
    if (buffer.size() > 0)
      value = buffer[0];
    else
      value = 0;

    return *this;
  }

  //! returns
  smart_stream &operator>>(short &value) {
    value = converter::to_short(buffer);
    return *this;
  }

  //! returns
  smart_stream &operator>>(unsigned short &value) {
    value = converter::to_unsigned_short(buffer);
    return *this;
  }

  //! returns
  smart_stream &operator>>(int &value) {
    value = converter::to_int(buffer);
    return *this;
  }

  //! returns
  smart_stream &operator>>(unsigned int &value) {
    value = converter::to_unsigned_int(buffer);
    return *this;
  }

  //! returns
  smart_stream &operator>>(long long &value) {
    value = converter::to_long_long(buffer);
    return *this;
  }

  //! returns
  smart_stream &operator>>(unsigned long long &value) {
    value = converter::to_unsigned_long_long(buffer);
    return *this;
  }

  //! returns
  smart_stream &operator>>(double &value) {
    value = converter::to_double(buffer);
    return *this;
  }

  //! returns
  smart_stream &operator>>(string &value) {
    value = buffer;
    return *this;
  }

  //! constructor
  smart_stream() {
    // nothing to do
  }

  //! destructor (non-virtual: please do not inherit from this class)
  ~smart_stream() {
    // nothing to do
  }
};

#endif
